# engine/catalog_manager.py (最终版)

import pickle
from os import path
from pysql_compiler.catalog import Catalog, TableSchema, IndexSchema

class CatalogManager:
    """负责管理数据库元数据（Catalog）的加载、持久化和访问。"""
    def __init__(self, db_file_path: str):
        self.catalog_path = db_file_path + ".catalog"
        self._catalog = self._load_catalog()

    def _load_catalog(self) -> Catalog:
        if path.exists(self.catalog_path) and path.getsize(self.catalog_path) > 0:
            with open(self.catalog_path, 'rb') as f:
                return pickle.load(f)
        else:
            return Catalog()

    def save_catalog(self):
        with open(self.catalog_path, 'wb') as f:
            pickle.dump(self._catalog, f)

    def create_table(self, table_name: str, columns: list, constraints: list = None):
        return self._catalog.create_table(table_name, columns, constraints)

    def create_index(self, index_name: str, table_name: str, column_name: str, root_page_id: int | None = None):
        index_schema = self._catalog.create_index(index_name, table_name, column_name, root_page_id)
        self.save_catalog()
        return index_schema

    def get_table_schema(self, table_name: str) -> TableSchema | None:
        return self._catalog.get_table_schema(table_name)

    
    def get_all_table_names(self) -> list[str]:
        """
        返回数据库中所有表的名称列表。
        这是为了支持前端UI显示数据库对象。
        """
        if self._catalog and hasattr(self._catalog, 'tables'):
            return list(self._catalog.tables.keys())
        return []
    

    def get_index_root_page_id(self, index_name: str) -> int:
        """获取B+树索引的根页面ID"""
        index_meta = self._catalog.indexes.get(index_name)
        if index_meta and 'root_page_id' in index_meta:
            return index_meta['root_page_id']
        raise RuntimeError(f"索引 '{index_name}' 或其元数据不存在。")

    def update_index_root_page_id(self, index_name: str, new_root_page_id: int):
        """更新B+树索引的根页面ID"""
        index_meta = self._catalog.indexes.get(index_name)
        if index_meta:
            index_meta['root_page_id'] = new_root_page_id
            self.save_catalog()
        else:
            raise RuntimeError(f"尝试更新一个不存在的索引 '{index_name}'。")

    def get_index_data_structure(self, index_name: str) -> dict | None:
        return self._catalog.indexes.get(index_name)

    def get_all_pages_for_table(self, table_name: str) -> list[int]:
        schema = self.get_table_schema(table_name)
        return schema.pages if schema else []

    def add_page_to_table(self, table_name: str, page_id: int):
        schema = self.get_table_schema(table_name)
        if schema:
            if page_id not in schema.pages:
                schema.pages.append(page_id)
                self.save_catalog()

    def get_table_owner_of_page(self, page_id: int) -> str | None:
        """
        查找并返回拥有指定页面的表名。
        如果页面未被任何表拥有，则返回 None。
        """
        for table_name, schema in self._catalog.tables.items():
            if page_id in schema.pages:
                return table_name
        return None

    def table_exists(self, table_name: str) -> bool:
        return self._catalog.table_exists(table_name)

    def add_column(self, table_name: str, column_name: str, data_type: str):
        """向表中添加一列"""
        schema = self.get_table_schema(table_name)
        if schema:
            schema.add_column(column_name, data_type)
            self.save_catalog()

    def drop_column(self, table_name: str, column_name: str):
        """从表中删除一列"""
        schema = self.get_table_schema(table_name)
        if schema and column_name in schema.columns:
            del schema.columns[column_name]
            schema.column_order.remove(column_name)
            self.save_catalog()

    def alter_column_type(self, table_name: str, column_name: str, new_data_type: str):
        """修改列的数据类型"""
        schema = self.get_table_schema(table_name)
        if schema and column_name in schema.columns:
            schema.columns[column_name] = new_data_type.upper()
            self.save_catalog()

    def add_primary_key(self, table_name: str, column_name: str):
        """添加主键约束"""
        print(f"[CatalogManager] Primary key on '{column_name}' of table '{table_name}' is noted.")
        self.save_catalog()